namespace GYLite {
    export class LoaderFactory {
        private _request: any;
        private _progress: (e: any) => void;
        public loadBitmap(blob: Blob, complete: (status: number) => void, obj: SeqLoader): void {
            if (GYLoader._disposed) return;
            let global: any = window;
            global.createImageBitmap(blob).then((response: any) => {
                obj.data = new egret.BitmapData(response);
                obj.data.source.src = obj.loadInfo.path;
                if (complete)
                    complete.call(obj, 200);
            });
        }
        public loadRes(url: string, type: LoadType, complete: (status: number) => void, obj: SeqLoader, progress: (percent: number) => void = null) {
            if (type == LoadType.TYPE_SOUND) {
                this.loadSound(<string>url, complete, obj);
                return;
            }
            //其他资源
            let imageLoader = GYLoader.miniGame ? GYLoader.miniGame.createImage() : new Image();
            imageLoader.crossOrigin = "*";
            imageLoader.onload = (e: Event) => {
                obj.data = new egret.BitmapData(e.target);
                if (complete)
                    complete.call(obj, 200);
            };
            imageLoader.onerror = (e: Event) => {
                obj.data = null;
                if (complete)
                    complete.call(obj, 404);
            };
            imageLoader.src = url;
        }
        /**数据加载请求
         * @param req 请求参数
         * @param type 数据类型
         * @param complete 完成回调
         * @param obj 请求的队列加载器
         * @param progress 进度回调
        */
        public loadData(req: URLRequest, type: LoadType, complete: (status: number) => void, obj: SeqURLLoader, progress: (e: any) => void = null) {
            let s = this;
            s._progress = progress;
            s.request(req, complete, obj, progress);
        }

        public loadSound(url: string, complete: (status: number) => void, obj: SeqLoader): void {
            let s = this;
            let soundLoader = new egret.Sound;
            soundLoader.addEventListener(egret.Event.COMPLETE, (e: egret.Event) => {
                if (GYLoader._disposed) return;
                obj.data = e.target;
                complete.call(obj, 200)
            }, s);
            soundLoader.addEventListener(egret.IOErrorEvent.IO_ERROR, (e: egret.IOErrorEvent) => {
                if (GYLoader._disposed) return;
                if (obj.bytes && GYLoader.supportBlobMP3 == 1 && obj.loadInfo.mimeType == "audio/mp3" || GYLoader.supportBlobWAV == 1 && obj.loadInfo.mimeType == "audio/wav") {
                    if (obj.loadInfo.mimeType == "audio/mp3") {
                        GYLoader.supportBlobMP3 = 2;
                        console.warn("可能不支持blob格式的MP3:" + obj.loadInfo.path);
                    }
                    else if (obj.loadInfo.mimeType == "audio/wav") {
                        console.warn("可能不支持blob格式的WAV:" + obj.loadInfo.path);
                        GYLoader.supportBlobWAV = 2;
                    }
                    obj.loadBytes(obj.bytes);
                    obj.bytes = null;
                    return;
                }
                complete.call(obj, 500);
            }, s);
            soundLoader.load(url);
        }
        /**xmlHttpRequest请求
         * @param req 请求参数
         * @param complete 完成回调
         * @param obj 请求的队列加载器
         * @param progress 进度回调
        */
        public request(req: URLRequest, complete: (status: number) => void, obj: SeqURLLoader, progress: (e: any) => void = null) {
            let s = this;
            if (GYLoader._disposed) return;
            let wxData: any;
            let request: any;
            if (GYLoader.miniGame)//优先判断微信的request
            {
                request = GYLoader.miniGame;
                wxData = {};
                wxData.method = req.method;
                wxData.responseType = req.dataFormat == "arraybuffer" ? req.dataFormat : "text";
                wxData.dataType = (req.dataFormat == "json" || req.dataFormat == "text") ? "text" : "other";
                wxData.url = req.url;
                wxData.header = {};
            }
            else if (window["XMLHttpRequest"]) {// code for all new browsers
                request = new XMLHttpRequest();
                request.addEventListener('progress', (e: any) => {
                    progress(e);
                });
            }
            else if (window["ActiveXObject"]) {// code for IE5 and IE6
                request = new window["ActiveXObject"]("Microsoft.XMLHTTP");
            }

            if (request == null) return;
            s._progress = progress;
            s._request = request;
            if (!wxData)//web的XMLHttpRequest请求初始化
            {
                request.open(req.method, req.url, true);
                request.responseType = req.dataFormat;//"arraybuffer";
                request.onreadystatechange = function () {
                    obj.loadInfo.progressInfo.push({ state: request.readyState, time: Date.now() - obj.loadInfo.startTime, status: request.status });
                    if (request.readyState == 4) {
                        var ioError = request.status != 200 && request.status != 0;
                        GYLite.TimeManager.timeOut(function (ioError: boolean): void {
                            obj.data = ioError ? null : request.response;
                            obj.loadInfo.status = request.status;
                            complete.call(obj, request.status);
                        }, s, 0, ioError)
                    }
                };
            }

            let i: number, len: number;
            len = req.requestHeaders ? req.requestHeaders.length : 0;
            if (len > 0) {
                for (i = 0; i < len; ++i) {
                    if (wxData)
                        wxData.header[req.requestHeaders[i].key] = req.requestHeaders[i].value;
                    else
                        request.setRequestHeader(req.requestHeaders[i].key, req.requestHeaders[i].value);
                }
            }
            let sendData: any;
            if (req.method == "get" || !req.data) {
            }
            else if (CommonUtil.GYIs(req.data, URLVariables)) {
                if (wxData)
                    wxData.header["Content-Type"] = "application/x-www-form-urlencoded";
                else
                    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                var urlVars = req.data;
                sendData = urlVars.toString();
            }
            else if (CommonUtil.GYIs(req.data, FormData)) {
                sendData = req.data;
            }
            else {
                if (req.contentType == "" || req.contentType == null) {
                    if (wxData)
                        wxData.header["Content-Type"] = "multipart/form-data";
                    else
                        request.setRequestHeader("Content-Type", "multipart/form-data");
                }
                sendData = req.data;
            }

            if (wxData) {
                if (req.contentType != "" && req.contentType != null)
                    wxData.header["Content-Type"] = req.contentType;
                wxData.success = (res: any) => {
                    obj.data = res;
                    complete.call(obj, res && res.statusCode ? res.statusCode : 500);
                };
                wxData.fail = () => {
                    obj.data = null;
                    complete.call(obj, 500);
                };
                wxData.data = sendData;
                request(wxData);
            }
            else {
                if (req.contentType != "" && req.contentType != null)
                    request.setRequestHeader("Content-Type", req.contentType);
                request.send(sendData);
            }
        }
        public close(): void {
            let s = this;
            if (s._request) 
                (<XMLHttpRequest>this._request).abort();            
        }

        public dispose(): void {
            let s = this;
            if (s._request) {
                s.close();
                if (s._progress)
                    s._request.removeEventListener('progress', s._progress);
            }            
            s._request = s._progress = null;
        }
    }
}